package kaang.dev.processes;

import kaang.dev.warpimage.NativeBridge;
import android.util.Log;

public class WarpingMatrix {
	float[][][][] matrixX;
	float[][][][] matrixY;
	int[][][] flag;
	
	int[] intensity = new int[]{15, 20, 25};
	int[] area = new int[]{10, 15, 20};
	private int active_kindID;
	private int active_areaID;
	private int active_intensityID;
	int width;
	int height;
	
	public WarpingMatrix(int w, int h)
	{
		width = w;
		height = h;
		
		int kind = 3;
		int area_ = 0;
		int intense = 0;
		
		setActive_areaID(area_);
		setActive_intensityID(intense);
		setActive_kindID(kind);
		
		// 6: kind of warp (left-right swirl, sphere in/out, move, undo)
		// 3: kind of area
		// 3: kind of intensity
		int maxarea = area[2] * width / 100  +  4;
		matrixX = new float[6][3][3][maxarea*maxarea];
		matrixY = new float[6][3][3][maxarea*maxarea];
		flag = new int[6][3][3];
		
		for (int i=0;i<6;i++)
			for(int j=0;j<3;j++)
				for(int t=0;t<3;t++)
					flag[i][j][t] = 0;
	}

	public WarpingMatrix(int w, int h, int kind, int area_, int intense)
	{
		width = w;
		height = h;
		
		setActive_areaID(area_);
		setActive_intensityID(intense);
		setActive_kindID(kind);
		
		// 6: kind of warp (left-right swirl, sphere in/out, move, undo)
		// 3: kind of area
		// 3: kind of intensity
		int maxarea = area[2] * width / 100  +  4;
		matrixX = new float[6][3][3][maxarea*maxarea];
		matrixY = new float[6][3][3][maxarea*maxarea];
		flag = new int[6][3][3];
		
		for (int i=0;i<6;i++)
			for(int j=0;j<3;j++)
				for(int t=0;t<3;t++)
					flag[i][j][t] = 0;
	}
	
	public int GetArea()
	{
		return area[active_areaID];
	}
	public int GetIntensity()
	{
		return intensity[active_intensityID];
	}
	public float[] TransformMatrixX()
	{
		if (active_kindID > 3)
			return null;
		if(flag[active_kindID][active_areaID][active_intensityID] == 0)
		{
			int range = area[active_areaID] * width / 100;
			int inten = intensity[active_intensityID];
			switch(active_kindID)
			{
				//		0. Pinch (Sphere in)
				// 		1. Push	 (Sphere out)
				// 		2. Left swirl
				//		3. Right swirl
				case 0:
					NativeBridge.getInstance().WarpCreateSphereInMattix(matrixX[active_kindID][active_areaID][active_intensityID], matrixY[active_kindID][active_areaID][active_intensityID], range, width, height, inten, 1);
					break;
				case 1:
					NativeBridge.getInstance().WarpCreateSphereOutMattix(matrixX[active_kindID][active_areaID][active_intensityID], matrixY[active_kindID][active_areaID][active_intensityID], range, width, height, inten, -1);
					break;
				case 2:
					NativeBridge.getInstance().WarpCreateSwirlMattix(matrixX[active_kindID][active_areaID][active_intensityID], matrixY[active_kindID][active_areaID][active_intensityID], range, width, height, inten, 1);
					break;
				case 3:
					NativeBridge.getInstance().WarpCreateSwirlMattix(matrixX[active_kindID][active_areaID][active_intensityID], matrixY[active_kindID][active_areaID][active_intensityID], range, width, height, inten, -1);
					break;
			}
			flag[active_kindID][active_areaID][active_intensityID] = 1;
		}
		return matrixX[active_kindID][active_areaID][active_intensityID];
	}
	public float[] TransformMatrixY()
	{
		if (active_kindID > 3)
			return null;
		if(flag[active_kindID][active_areaID][active_intensityID] == 0)
		{
			int range = area[active_areaID] * width / 100;
			int inten = intensity[active_intensityID];
			switch(active_kindID)
			{
				//			0. Pinch (Sphere in)
				// 		1. Push	 (Sphere out)
				// 		2. Left swirl
				//		3. Right swirl
				case 0:
					NativeBridge.getInstance().WarpCreateSphereInMattix(matrixX[active_kindID][active_areaID][active_intensityID], matrixY[active_kindID][active_areaID][active_intensityID], range, width, height, inten, 1);
					break;
				case 1:
					NativeBridge.getInstance().WarpCreateSphereOutMattix(matrixX[active_kindID][active_areaID][active_intensityID], matrixY[active_kindID][active_areaID][active_intensityID], range, width, height, inten, -1);
					break;
				case 2:
					NativeBridge.getInstance().WarpCreateSwirlMattix(matrixX[active_kindID][active_areaID][active_intensityID], matrixY[active_kindID][active_areaID][active_intensityID], range, width, height, inten, 1);
					break;
				case 3:
					NativeBridge.getInstance().WarpCreateSwirlMattix(matrixX[active_kindID][active_areaID][active_intensityID], matrixY[active_kindID][active_areaID][active_intensityID], range, width, height, inten, -1);
					break;
			}
			flag[active_kindID][active_areaID][active_intensityID] = 1;
		}
		return matrixY[active_kindID][active_areaID][active_intensityID];
	}
	
	private void CreateSwirlMatrix(float[] matrixX, float[] matrixY, int w, int h, int area, int intensity, int direction)
	{
		float theta;
		float newX, newY;
		float changeVectorX, changeVectorY;

		float intensity_new = intensity / 600.0f;
		int radius = area / 2;

		int x,y;
		int i, j;
		int index;
		int count = 0;
		for(i = - radius; i <= radius; i++)
		{
			for(j = -radius; j<= 0; j++)
			{
				float local_radius = (float)Math.sqrt(i*i + j*j);
				changeVectorX = 0;
				changeVectorY = 0;
				if(local_radius <= radius)
				{
					theta = (float)Math.atan2(j, i);
					//LOGI("angel = %8.3f, radius = %8.3f, intensity = %d", theta, local_radius, intensity_new);
					float driftX = (float)(local_radius * Math.cos(theta + intensity_new * (radius - local_radius) * direction));
					float driftY = (float)(local_radius * Math.sin(theta + intensity_new * (radius - local_radius) * direction));

					newX = driftX;
					newY = driftY;

					changeVectorX = newX - i;
					changeVectorY = newY - j;
				}
				
				// value for (-x,-y)
				index = (j + radius) * area + (i + radius);
				matrixX[index] = changeVectorX;
				matrixY[index] = changeVectorY;
				
				//value for (x, y)
				index = (-j + radius) * area + (-i + radius);
				matrixX[index] = -changeVectorX;
				matrixY[index] = -changeVectorY;
			}
				//LOGI("%d %d %8.3f %8.3f %8.3f %8.3f", x, y, driftX, driftY, fp[id].X, fp[id].Y);

		}
	}

	public int getActive_kindID() {
		return active_kindID;
	}

	public void setActive_kindID(int active_kindID) {
		this.active_kindID = active_kindID;
	}

	public int getActive_areaID() {
		return active_areaID;
	}

	public void setActive_areaID(int active_areaID) {
		this.active_areaID = active_areaID;
	}

	public int getActive_intensityID() {
		return active_intensityID;
	}

	public void setActive_intensityID(int active_intensityID) {
		this.active_intensityID = active_intensityID;
	}
}
